<?php
namespace app\admin\controller\curd;
use app\admin\controller\curd\service\BuildColumn;
use app\admin\controller\curd\service\BuildForm;
use app\admin\controller\curd\service\BuildSearch;
use app\admin\controller\curd\service\BuildControllerProgram;
use app\admin\controller\curd\service\BuildModelFunction;
use app\admin\controller\curd\service\BuildSql;
use app\common\controller\AdminBase;
use app\common\model\AuthRuleModel;
use think\exception\ValidateException;
use think\helper\Str;
use utils\Data;

class Curd extends AdminBase
{
    const VERSION = '1.0.0';

    //创建form表单
    protected BuildForm $buildForm;

    //创建搜索条件
    protected BuildSearch $buildSearch;

    //创建控制器程序
    protected BuildControllerProgram $buildControllerProgram;

    //创建列
    protected BuildColumn $buildColumn;

    //创建model函数
    protected BuildModelFunction $buildModelFunction;

    //创建sql
    protected BuildSql $buildSql;

    public function initialize()
    {
        parent::initialize();
        $this->buildForm = new BuildForm();
        $this->buildSearch = new BuildSearch();
        $this->buildControllerProgram = new BuildControllerProgram();
        $this->buildColumn = new BuildColumn();
        $this->buildModelFunction = new BuildModelFunction();
        $this->buildSql = new BuildSql();
    }

    public function create()
    {
        if( $this->request->isPost() ) {
            $class = $this->request->post('class');
            $classname = $this->request->post('classname');
            if( empty($class) || empty($classname) ) {
                $this->error('请输入完整信息');
            }
            if ( $this->request->post('tpl_type') == '' ) {
                $this->error('请选择模板类型');
            }
            $data = [
                'class' => $class,
                'classname' => $classname,
                'tpl_type' => $this->request->post('tpl_type'),
                'model' => $this->request->post('model'),
                'view' => $this->request->post('view'),
                'table' => $this->request->post('table'),
                'auth' => $this->request->post('auth'),
                'pid' => $this->request->post('pid'),
                'table_data' => $this->request->post('table_data'),
            ];

            /**
             * 生成前先检测
             */
            if (!$this->check($data, $error_html))
            {
                $this->error($error_html);
            }

            //------开始生成-----
            //导入table
            $ret_msg = '';
            if( $data['table'] == 1 ) {
                $this->createTable($data, $msg);
                $ret_msg .= $msg."<br/>";
            }

            //生成控制器
            $this->createController($data, $msg);
            $ret_msg .= $msg."<br/>";

            //生成model
            if( $data['model'] == 1 ) {
                $this->createModel($data, $msg);
                $ret_msg .= $msg."<br/>";
            }

            //生成模版
            if( $data['view'] == 1 ) {
                $this->createTpl($data, $msg);
                $ret_msg .= $msg."<br/>";
            }

            //设置菜单
            if( $data['auth'] == 1 ) {
                $this->createAuth($data, $msg);
                $ret_msg .= $msg."<br/>";
            }

            $this->success($ret_msg);
        }

        $list = AuthRuleModel::select()->toArray();
        $authList = Data::tree($list, 'title','id');
        $view_path = $this->controllerPath().'curd'.DIRECTORY_SEPARATOR.'view'.DIRECTORY_SEPARATOR.'create.html';
		return view($view_path, compact('authList'))->filter(function($content){
            return str_replace("&amp;emsp;",'&emsp;',$content);
        });

        // return view($view_path,compact('authList'))->filter(function($content){
        //     return str_replace("&amp;emsp;",'&emsp;',$content);
        // });
    }

    protected function check($data, &$error_html)
    {
        $class = $data['class'];
        $studly_class = str::studly($class); //首字符大写的驼峰
        $snake_class = str::snake($class); //下划线小写
        $check = true;
        //检测控制器是否存在
        $createPath = $this->controllerPath().$studly_class.'.php';
        $error_html = '';
        if( file_exists($createPath) ) {
            $error_html .= "<div style='color: #ff0000'>控制器文件已存在：{$createPath}</div><br>";
            $check = false;
        }
        //检测model是否存在
        $createPath = $this->modelPath().$studly_class.'Model.php';
        if( file_exists($createPath) ) {
            $error_html .= "<div style='color: #ff0000'>model文件已存在：{$createPath}</div><br>";
            $check = false;
        }
        //检测模版是否存在
        $createPath = $this->viewPath() . $snake_class.DIRECTORY_SEPARATOR.'index.html';
        if( file_exists($createPath) ) {
            $error_html .= "<div style='color: #ff0000'>模版文件已存在：{$createPath}</div><br>";
            $check = false;
        }
        //检测菜单是否存在
        $name = 'admin'.DIRECTORY_SEPARATOR.$snake_class.DIRECTORY_SEPARATOR.'index';
        if( AuthRuleModel::where('name', $name)->find() ) {
            $error_html .= "<div style='color: #ff0000'>菜单权限已存在</div><br>";
            $check = false;
        }
        return $check;
    }

    /**
     * 创建控制器
     */
    protected function createController($data, &$msg='')
    {
        $class = $data['class'];
        $classname = $data['classname'];
        //转化为首字符大写的驼峰
        $class = str::studly($class);

        //生成的文件路径
        $createPath = $this->controllerPath().$class.'.php';

        /*if( file_exists($createPath) ) {
            $msg = "<div style='color: #ff0000'>控制器文件已存在：{$createPath}</div>";
            return false;
        }*/

        if ($data['tpl_type'] == 1) {
            $content = $this->getFile('index_layui');
        } else {
            $content = $this->getFile('index');
        }
        $content = str_replace('$$XNADMIN$$', $class, $content);
        $content = str_replace('$$CLASSNAME$$', $classname, $content);

        $search_condition = $this->buildControllerProgram->buildSearch($data['table_data']);
        $raw_data = $this->buildControllerProgram->buildRawData($data['table_data']);
        $content = str_replace('$$SEARCH_CONDITION$$', $search_condition, $content);
        $content = str_replace('$$RAW_DATA$$', $raw_data, $content);

        file_put_contents($createPath, $content);
        $msg = "<div style='color: #16b777'>控制器创建成功：{$createPath}</div>";
    }

    //创建model
    protected function createModel($data, &$msg='')
    {
        $class = $data['class'];
        $table_name = str::snake($class);

        //转化为首字符大写的驼峰
        $class = str::studly($class);

        //生成的文件路径
        $createPath = $this->modelPath().$class.'Model.php';
        /*if( file_exists($createPath) ) {
            $msg = "<div style='color: #ff0000'>model文件已存在：{$createPath}</div>";
            return false;
        }*/

        $content = $this->getFile('model');
        $function = $this->buildModelFunction->build($data['table_data']);
        $content = str_replace('$$FUNCTION$$', $function, $content);
        $content = str_replace('$$XNADMIN$$', $class.'Model', $content);
        $content = str_replace('$$TABLENAME$$', $table_name, $content);

        file_put_contents($createPath, $content);
        $msg = "<div style='color: #16b777'>model创建成功：{$createPath}</div>";
    }

    protected function createTpl($data, &$msg='')
    {
        $class = $data['class'];
        $classname = $data['classname'];
        $table_name = str::snake($class);

        $path = $this->viewPath() . $table_name;
        if( !file_exists($path) ) {
            mkdir($path, 0777);
        }

        $msg = '';
        //------------- 生成index.html ----------------
        if ($data['tpl_type'] == 1) {
            $index_content = $this->getFile('tpl_index_layui.html');
            $layui_column = $this->buildColumn->buildLayuiColumn($data['table_data']);
            $index_content = str_replace('$$LAYUI_COLUMN$$', $layui_column, $index_content);
        } else {
            $index_content = $this->getFile('tpl_index.html');
            //index列
            $head_html = $this->buildColumn->buildHead($data['table_data']);
            $body_html = $this->buildColumn->buildBody($data['table_data']);
            $index_content = str_replace('$$HEAD_HTML$$', $head_html, $index_content);
            $index_content = str_replace('$$BODY_HTML$$', $body_html, $index_content);
        }
        //index搜索
        $search_html = $this->buildSearch->build($data['table_data']);

        $index_content = str_replace('$$CLASSNAME$$', $classname, $index_content);
        $index_content = str_replace('$$SEARCH_HTML$$', $search_html, $index_content);
        $createPath = $path.'/index.html';


        file_put_contents($createPath, $index_content);
        $msg .= "<div style='color: #16b777'>index模版文件创建成功：{$createPath}</div>";
        /*if( file_exists($createPath) ) {
            $msg .= "<div style='color: #ff0000'>index模版文件已存在：{$createPath}</div>";
        } else {
            file_put_contents($createPath, $index_content);
            $msg .= "<div style='color: #16b777'>index模版文件创建成功：{$createPath}</div>";
        }*/


        //------------- 生成form.html ----------------
        $form_content = $this->getFile('tpl_form.html');
        $createPath = $path.DIRECTORY_SEPARATOR.'form.html';
        $form_html = $this->buildForm->build($data['table_data']); //根据数据生成表单
        $editor_html = $this->buildForm->buildEditorJs($data['table_data']);
        $form_content = str_replace('$$FORM_HTML$$', $form_html, $form_content);
        $form_content = str_replace('$$EDITOR_HTML$$', $editor_html, $form_content);

        file_put_contents($createPath, $form_content);
        $msg .= "<div style='color: #16b777'>form模版文件创建成功：{$createPath}</div>";
        /*if( file_exists($createPath) ) {
            $msg .= "<div style='color: #ff0000'>form模版文件已存在：{$createPath}</div>";
        } else {
            file_put_contents($createPath, $form_content);
            $msg .= "<div style='color: #16b777'>form模版文件创建成功：{$createPath}</div>";
        }*/
    }

    protected function createTable($data, &$msg='')
    {
        $class = $data['class'];
        $table_name = 'xn_'.str::snake($class);
        $sql = $this->buildSql->build($data['table_data'], $table_name);
        $info = "mysql:dbname=".env('DB_NAME').";host=".env('DB_HOST')."";
        $db   = new \PDO($info, env('DB_USER'), env('DB_PASS'));
        $db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, 0);

        try {
            $res = $db->exec($sql);
            $msg = "<div style='color: #16b777'>数据表{$table_name}：导入成功</div>";
            return true;
        } catch (ValidateException $e) {
            $msg = "<div style='color: #ff0000'>数据表创建失败：</div>{$e->getMessage()}";
            retError($msg);
        } catch (\Exception $e) {
            $msg = "<div style='color: #ff0000'>数据表创建失败：</div>{$e->getMessage()}";
            retError($msg);
        }
    }

    protected function createAuth($data, &$msg='')
    {
        $class = $data['class'];
        $table_name = str::snake($class);
        $name = "admin/{$table_name}/index";
        if( AuthRuleModel::where('name', $name)->find() ) {
            $msg = "<div style='color: #ff0000'>菜单权限已存在</div>";
            exit();
        }
        $insertData = [
            'pid' => $data['pid'],
            'name' => $name,
            'title' => $data['classname'].'管理',
            'is_menu' => 1,
            'icon' =>$data['pid'] == 0 ? 'layui-icon-app' :''
        ];
        $res = AuthRuleModel::create($insertData);

        /*if( in_array('add', $data['funs']) ) {

        }*/
        $msg = "<div style='color: #16b777'>菜单权限添加成功</div>";
    }

    //获取要复制的文件
    protected function getFile($filename)
    {
        return file_get_contents($this->templatePath(). $filename);
    }

    //template物理路径
    protected function templatePath()
    {
        return app_path() . 'controller'.DIRECTORY_SEPARATOR.'curd'.DIRECTORY_SEPARATOR.'template'.DIRECTORY_SEPARATOR;
    }

    //生成控制器路径
    protected function controllerPath()
    {
        return app_path() . 'controller'.DIRECTORY_SEPARATOR;
    }

    //生成model路径
    protected function modelPath()
    {
        return base_path() . 'common'.DIRECTORY_SEPARATOR.'model'.DIRECTORY_SEPARATOR;
    }

    //生成模版路径
    protected function viewPath()
    {
        return app_path() . 'view'.DIRECTORY_SEPARATOR;
    }
}
